home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 2 / Meeting Pearls Vol. II (1995)(GTI - Schatztruhe)[!].iso / Pearls / gfx / pbm / source / jpegV5.lha / jpegV5 / src / djpeg.c < prev    next >
C/C++ Source or Header  |  1994-12-23  |  22KB  |  737 lines

  1. /*
  2.  * djpeg.c
  3.  *
  4.  * Copyright (C) 1991-1994, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains a command-line user interface for the JPEG decompressor.
  9.  * It should work on any system with Unix- or MS-DOS-style command lines.
  10.  *
  11.  * Two different command line styles are permitted, depending on the
  12.  * compile-time switch TWO_FILE_COMMANDLINE:
  13.  *    djpeg [options]  inputfile outputfile
  14.  *    djpeg [options]  [inputfile]
  15.  * In the second style, output is always to standard output, which you'd
  16.  * normally redirect to a file or pipe to some other program.  Input is
  17.  * either from a named file or from standard input (typically redirected).
  18.  * The second style is convenient on Unix but is unhelpful on systems that
  19.  * don't support pipes.  Also, you MUST use the first style if your system
  20.  * doesn't do binary I/O to stdin/stdout.
  21.  * To simplify script writing, the "-outfile" switch is provided.  The syntax
  22.  *    djpeg [options]  -outfile outputfile  inputfile
  23.  * works regardless of which command line style is used.
  24.  */
  25.  
  26. #include "cdjpeg.h"        /* Common decls for cjpeg/djpeg applications */
  27. #define JMAKE_MSG_TABLE
  28. #include "cderror.h"        /* create message string table */
  29. #include "jversion.h"        /* for version message */
  30.  
  31. #include <ctype.h>        /* to declare isupper(),tolower(),isprint() */
  32. #ifdef NEED_SIGNAL_CATCHER
  33. #include <signal.h>        /* to declare signal() */
  34. #endif
  35. #ifdef USE_SETMODE
  36. #include <fcntl.h>        /* to declare setmode()'s parameter macros */
  37. /* If you have setmode() but not <io.h>, just delete this line: */
  38. #include <io.h>            /* to declare setmode() */
  39. #endif
  40.  
  41. #ifdef USE_CCOMMAND        /* command-line reader for Macintosh */
  42. #ifdef __MWERKS__
  43. #include <SIOUX.h>              /* Metrowerks declares it here */
  44. #endif
  45. #ifdef THINK_C
  46. #include <console.h>        /* Think declares it here */
  47. #endif
  48. #endif
  49.  
  50. #ifdef DONT_USE_B_MODE        /* define mode parameters for fopen() */
  51. #define READ_BINARY    "r"
  52. #define WRITE_BINARY    "w"
  53. #else
  54. #define READ_BINARY    "rb"
  55. #define WRITE_BINARY    "wb"
  56. #endif
  57.  
  58. #ifndef EXIT_FAILURE        /* define exit() codes if not provided */
  59. #define EXIT_FAILURE  1
  60. #endif
  61. #ifndef EXIT_SUCCESS
  62. #ifdef VMS
  63. #define EXIT_SUCCESS  1        /* VMS is very nonstandard */
  64. #else
  65. #define EXIT_SUCCESS  0
  66. #endif
  67. #endif
  68. #ifndef EXIT_WARNING
  69. #ifdef VMS
  70. #define EXIT_WARNING  1        /* VMS is very nonstandard */
  71. #else
  72. #define EXIT_WARNING  2
  73. #endif
  74. #endif
  75.  
  76.  
  77. /*
  78.  * This list defines the known output image formats
  79.  * (not all of which need be supported by a given version).
  80.  * You can change the default output format by defining DEFAULT_FMT;
  81.  * indeed, you had better do so if you undefine PPM_SUPPORTED.
  82.  */
  83.  
  84. typedef enum {
  85.     FMT_BMP,        /* BMP format (Windows flavor) */
  86.     FMT_GIF,        /* GIF format */
  87.     FMT_OS2,        /* BMP format (OS/2 flavor) */
  88.     FMT_PPM,        /* PPM/PGM (PBMPLUS formats) */
  89.     FMT_RLE,        /* RLE format */
  90.     FMT_TARGA,        /* Targa format */
  91.     FMT_TIFF        /* TIFF format */
  92. } IMAGE_FORMATS;
  93.  
  94. #ifndef DEFAULT_FMT        /* so can override from CFLAGS in Makefile */
  95. #define DEFAULT_FMT    FMT_PPM
  96. #endif
  97.  
  98. static IMAGE_FORMATS requested_fmt;
  99.  
  100.  
  101. /*
  102.  * Signal catcher to ensure that temporary files are removed before aborting.
  103.  * NB: for Amiga Manx C this is actually a global routine named _abort();
  104.  * we put "#define signal_catcher _abort" in jconfig.h.  Talk about bogus...
  105.  */
  106.  
  107. #ifdef NEED_SIGNAL_CATCHER
  108.  
  109. static j_common_ptr sig_cinfo;
  110.  
  111. GLOBAL void
  112. signal_catcher (int signum)
  113. {
  114.   if (sig_cinfo != NULL) {
  115.     if (sig_cinfo->err != NULL) /* turn off trace output */
  116.       sig_cinfo->err->trace_level = 0;
  117.     jpeg_destroy(sig_cinfo);    /* clean up memory allocation & temp files */
  118.   }
  119.   exit(EXIT_FAILURE);
  120. }
  121.  
  122. #endif
  123.  
  124.  
  125. /*
  126.  * Optional routine to display a percent-done figure on stderr.
  127.  */
  128.  
  129. #ifdef PROGRESS_REPORT
  130.  
  131. METHODDEF void
  132. progress_monitor (j_common_ptr cinfo)
  133. {
  134.   cd_progress_ptr prog = (cd_progress_ptr) cinfo->progress;
  135.   int total_passes = prog->pub.total_passes + prog->total_extra_passes;
  136.   int percent_done = (int) (prog->pub.pass_counter*100L/prog->pub.pass_limit);
  137.  
  138.   if (percent_done != prog->percent_done) {
  139.     prog->percent_done = percent_done;
  140.     if (total_passes > 1) {
  141.       fprintf(stderr, "\rPass %d/%d: %3d%% ",
  142.           prog->pub.completed_passes + prog->completed_extra_passes + 1,
  143.           total_passes, percent_done);
  144.     } else {
  145.       fprintf(stderr, "\r %3d%% ", percent_done);
  146.     }
  147.     fflush(stderr);
  148.   }
  149. }
  150.  
  151. #endif
  152.  
  153.  
  154. /*
  155.  * Argument-parsing code.
  156.  * The switch parser is designed to be useful with DOS-style command line
  157.  * syntax, ie, intermixed switches and file names, where only the switches
  158.  * to the left of a given file name affect processing of that file.
  159.  * The main program in this file doesn't actually use this capability...
  160.  */
  161.  
  162.  
  163. static const char * progname;    /* program name for error messages */
  164. static char * outfilename;    /* for -outfile switch */
  165.  
  166.  
  167. LOCAL void
  168. usage (void)
  169. /* complain about bad command line */
  170. {
  171.   fprintf(stderr, "usage: %s [switches] ", progname);
  172. #ifdef TWO_FILE_COMMANDLINE
  173.   fprintf(stderr, "inputfile outputfile\n");
  174. #else
  175.   fprintf(stderr, "[inputfile]\n");
  176. #endif
  177.  
  178.   fprintf(stderr, "Switches (names may be abbreviated):\n");
  179.   fprintf(stderr, "  -colors N      Reduce image to no more than N colors\n");
  180.   fprintf(stderr, "  -fast          Fast, low-quality processing\n");
  181.   fprintf(stderr, "  -grayscale     Force grayscale output\n");
  182. #ifdef IDCT_SCALING_SUPPORTED
  183.   fprintf(stderr, "  -scale M/N     Scale output image by fraction M/N, eg, 1/8\n");
  184. #endif
  185. #ifdef BMP_SUPPORTED
  186.   fprintf(stderr, "  -bmp           Select BMP output format (Windows style)%s\n",
  187.       (DEFAULT_FMT == FMT_BMP ? " (default)" : ""));
  188. #endif
  189. #ifdef GIF_SUPPORTED
  190.   fprintf(stderr, "  -gif           Select GIF output format%s\n",
  191.       (DEFAULT_FMT == FMT_GIF ? " (default)" : ""));
  192. #endif
  193. #ifdef BMP_SUPPORTED
  194.   fprintf(stderr, "  -os2           Select BMP output format (OS/2 style)%s\n",
  195.       (DEFAULT_FMT == FMT_OS2 ? " (default)" : ""));
  196. #endif
  197. #ifdef PPM_SUPPORTED
  198.   fprintf(stderr, "  -pnm           Select PBMPLUS (PPM/PGM) output format%s\n",
  199.       (DEFAULT_FMT == FMT_PPM ? " (default)" : ""));
  200. #endif
  201. #ifdef RLE_SUPPORTED
  202.   fprintf(stderr, "  -rle           Select Utah RLE output format%s\n",
  203.       (DEFAULT_FMT == FMT_RLE ? " (default)" : ""));
  204. #endif
  205. #ifdef TARGA_SUPPORTED
  206.   fprintf(stderr, "  -targa         Select Targa output format%s\n",
  207.       (DEFAULT_FMT == FMT_TARGA ? " (default)" : ""));
  208. #endif
  209.   fprintf(stderr, "Switches for advanced users:\n");
  210. #ifdef DCT_ISLOW_SUPPORTED
  211.   fprintf(stderr, "  -dct int       Use integer DCT method%s\n",
  212.       (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
  213. #endif
  214. #ifdef DCT_IFAST_SUPPORTED
  215.   fprintf(stderr, "  -dct fast      Use fast integer DCT (less accurate)%s\n",
  216.       (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
  217. #endif
  218. #ifdef DCT_FLOAT_SUPPORTED
  219.   fprintf(stderr, "  -dct float     Use floating-point DCT method%s\n",
  220.       (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
  221. #endif
  222.   fprintf(stderr, "  -dither fs     Use F-S dithering (default)\n");
  223.   fprintf(stderr, "  -dither none   Don't use dithering in quantization\n");
  224.   fprintf(stderr, "  -dither ordered  Use ordered dither (medium speed, quality)\n");
  225. #ifdef QUANT_2PASS_SUPPORTED
  226.   fprintf(stderr, "  -map FILE      Map to colors used in named image file\n");
  227. #endif
  228.   fprintf(stderr, "  -nosmooth      Don't use high-quality upsampling\n");
  229. #ifdef QUANT_1PASS_SUPPORTED
  230.   fprintf(stderr, "  -onepass       Use 1-pass quantization (fast, low quality)\n");
  231. #endif
  232.   fprintf(stderr, "  -maxmemory N   Maximum memory to use (in kbytes)\n");
  233.   fprintf(stderr, "  -outfile name  Specify name for output file\n");
  234.   fprintf(stderr, "  -verbose  or  -debug   Emit debug output\n");
  235.   exit(EXIT_FAILURE);
  236. }
  237.  
  238.  
  239. LOCAL boolean
  240. keymatch (char * arg, const char * keyword, int minchars)
  241. /* Case-insensitive matching of (possibly abbreviated) keyword switches. */
  242. /* keyword is the constant keyword (must be lower case already), */
  243. /* minchars is length of minimum legal abbreviation. */
  244. {
  245.   register int ca, ck;
  246.   register int nmatched = 0;
  247.  
  248.   while ((ca = *arg++) != '\0') {
  249.     if ((ck = *keyword++) == '\0')
  250.       return FALSE;        /* arg longer than keyword, no good */
  251.     if (isupper(ca))        /* force arg to lcase (assume ck is already) */
  252.       ca = tolower(ca);
  253.     if (ca != ck)
  254.       return FALSE;        /* no good */
  255.     nmatched++;            /* count matched characters */
  256.   }
  257.   /* reached end of argument; fail if it's too short for unique abbrev */
  258.   if (nmatched < minchars)
  259.     return FALSE;
  260.   return TRUE;            /* A-OK */
  261. }
  262.  
  263.  
  264. LOCAL int
  265. parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
  266.         int last_file_arg_seen, boolean for_real)
  267. /* Parse optional switches.
  268.  * Returns argv[] index of first file-name argument (== argc if none).
  269.  * Any file names with indexes <= last_file_arg_seen are ignored;
  270.  * they have presumably been processed in a previous iteration.
  271.  * (Pass 0 for last_file_arg_seen on the first or only iteration.)
  272.  * for_real is FALSE on the first (dummy) pass; we may skip any expensive
  273.  * processing.
  274.  */
  275. {
  276.   int argn;
  277.   char * arg;
  278.  
  279.   /* Set up default JPEG parameters. */
  280.   requested_fmt = DEFAULT_FMT;    /* set default output file format */
  281.   outfilename = NULL;
  282.   cinfo->err->trace_level = 0;
  283.  
  284.   /* Scan command line options, adjust parameters */
  285.  
  286.   for (argn = 1; argn < argc; argn++) {
  287.     arg = argv[argn];
  288.     if (*arg != '-') {
  289.       /* Not a switch, must be a file name argument */
  290.       if (argn <= last_file_arg_seen) {
  291.     outfilename = NULL;    /* -outfile applies to just one input file */
  292.     continue;        /* ignore this name if previously processed */
  293.       }
  294.       break;            /* else done parsing switches */
  295.     }
  296.     arg++;            /* advance past switch marker character */
  297.  
  298.     if (keymatch(arg, "bmp", 1)) {
  299.       /* BMP output format. */
  300.       requested_fmt = FMT_BMP;
  301.  
  302.     } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) ||
  303.            keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) {
  304.       /* Do color quantization. */
  305.       int val;
  306.  
  307.       if (++argn >= argc)    /* advance to next argument */
  308.     usage();
  309.       if (sscanf(argv[argn], "%d", &val) != 1)
  310.     usage();
  311.       cinfo->desired_number_of_colors = val;
  312.       cinfo->quantize_colors = TRUE;
  313.  
  314.     } else if (keymatch(arg, "dct", 2)) {
  315.       /* Select IDCT algorithm. */
  316.       if (++argn >= argc)    /* advance to next argument */
  317.     usage();
  318.       if (keymatch(argv[argn], "int", 1)) {
  319.     cinfo->dct_method = JDCT_ISLOW;
  320.       } else if (keymatch(argv[argn], "fast", 2)) {
  321.     cinfo->dct_method = JDCT_IFAST;
  322.       } else if (keymatch(argv[argn], "float", 2)) {
  323.     cinfo->dct_method = JDCT_FLOAT;
  324.       } else
  325.     usage();
  326.  
  327.     } else if (keymatch(arg, "dither", 2)) {
  328.       /* Select dithering algorithm. */
  329.       if (++argn >= argc)    /* advance to next argument */
  330.     usage();
  331.       if (keymatch(argv[argn], "fs", 2)) {
  332.     cinfo->dither_mode = JDITHER_FS;
  333.       } else if (keymatch(argv[argn], "none", 2)) {
  334.     cinfo->dither_mode = JDITHER_NONE;
  335.       } else if (keymatch(argv[argn], "ordered", 2)) {
  336.     cinfo->dither_mode = JDITHER_ORDERED;
  337.       } else
  338.     usage();
  339.  
  340.     } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
  341.       /* Enable debug printouts. */
  342.       /* On first -d, print version identification */
  343.       static boolean printed_version = FALSE;
  344.  
  345.       if (! printed_version) {
  346.     fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n",
  347.         JVERSION, JCOPYRIGHT);
  348.     printed_version = TRUE;
  349.       }
  350.       cinfo->err->trace_level++;
  351.  
  352.     } else if (keymatch(arg, "fast", 1)) {
  353.       /* Select recommended processing options for quick-and-dirty output. */
  354.       cinfo->two_pass_quantize = FALSE;
  355.       cinfo->dither_mode = JDITHER_ORDERED;
  356.       if (! cinfo->quantize_colors) /* don't override an earlier -colors */
  357.     cinfo->desired_number_of_colors = 216;
  358.       cinfo->dct_method = JDCT_FASTEST;
  359.       cinfo->do_fancy_upsampling = FALSE;
  360.  
  361.     } else if (keymatch(arg, "gif", 1)) {
  362.       /* GIF output format. */
  363.       requested_fmt = FMT_GIF;
  364.  
  365.     } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
  366.       /* Force monochrome output. */
  367.       cinfo->out_color_space = JCS_GRAYSCALE;
  368.  
  369.     } else if (keymatch(arg, "map", 3)) {
  370.       /* Quantize to a color map taken from an input file. */
  371.       if (++argn >= argc)    /* advance to next argument */
  372.     usage();
  373.       if (for_real) {        /* too expensive to do twice! */
  374. #ifdef QUANT_2PASS_SUPPORTED    /* otherwise can't quantize to supplied map */
  375.     FILE * mapfile;
  376.  
  377.     if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) {
  378.       fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
  379.       exit(EXIT_FAILURE);
  380.     }
  381.     read_color_map(cinfo, mapfile);
  382.     fclose(mapfile);
  383.     cinfo->quantize_colors = TRUE;
  384. #else
  385.     ERREXIT(cinfo, JERR_NOT_COMPILED);
  386. #endif
  387.       }
  388.  
  389.     } else if (keymatch(arg, "maxmemory", 3)) {
  390.       /* Maximum memory in Kb (or Mb with 'm'). */
  391.       long lval;
  392.       char ch = 'x';
  393.  
  394.       if (++argn >= argc)    /* advance to next argument */
  395.     usage();
  396.       if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
  397.     usage();
  398.       if (ch == 'm' || ch == 'M')
  399.     lval *= 1000L;
  400.       cinfo->mem->max_memory_to_use = lval * 1000L;
  401.  
  402.     } else if (keymatch(arg, "nosmooth", 3)) {
  403.       /* Suppress fancy upsampling */
  404.       cinfo->do_fancy_upsampling = FALSE;
  405.  
  406.     } else if (keymatch(arg, "onepass", 3)) {
  407.       /* Use fast one-pass quantization. */
  408.       cinfo->two_pass_quantize = FALSE;
  409.  
  410.     } else if (keymatch(arg, "os2", 3)) {
  411.       /* BMP output format (OS/2 flavor). */
  412.       requested_fmt = FMT_OS2;
  413.  
  414.     } else if (keymatch(arg, "outfile", 4)) {
  415.       /* Set output file name. */
  416.       if (++argn >= argc)    /* advance to next argument */
  417.     usage();
  418.       outfilename = argv[argn];    /* save it away for later use */
  419.  
  420.     } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) {
  421.       /* PPM/PGM output format. */
  422.       requested_fmt = FMT_PPM;
  423.  
  424.     } else if (keymatch(arg, "rle", 1)) {
  425.       /* RLE output format. */
  426.       requested_fmt = FMT_RLE;
  427.  
  428.     } else if (keymatch(arg, "scale", 1)) {
  429.       /* Scale the output image by a fraction M/N. */
  430.       if (++argn >= argc)    /* advance to next argument */
  431.     usage();
  432.       if (sscanf(argv[argn], "%d/%d",
  433.          &cinfo->scale_num, &cinfo->scale_denom) != 2)
  434.     usage();
  435.  
  436.     } else if (keymatch(arg, "targa", 1)) {
  437.       /* Targa output format. */
  438.       requested_fmt = FMT_TARGA;
  439.  
  440.     } else {
  441.       usage();            /* bogus switch */
  442.     }
  443.   }
  444.  
  445.   return argn;            /* return index of next arg (file name) */
  446. }
  447.  
  448.  
  449. /*
  450.  * Marker processor for COM markers.
  451.  * This replaces the library's built-in processor, which just skips the marker.
  452.  * We want to print out the marker as text, if possible.
  453.  * Note this code relies on a non-suspending data source.
  454.  */
  455.  
  456. LOCAL unsigned int
  457. jpeg_getc (j_decompress_ptr cinfo)
  458. /* Read next byte */
  459. {
  460.   struct jpeg_source_mgr * datasrc = cinfo->src;
  461.  
  462.   if (datasrc->bytes_in_buffer == 0) {
  463.     if (! (*datasrc->fill_input_buffer) (cinfo))
  464.       ERREXIT(cinfo, JERR_CANT_SUSPEND);
  465.   }
  466.   datasrc->bytes_in_buffer--;
  467.   return GETJOCTET(*datasrc->next_input_byte++);
  468. }
  469.  
  470.  
  471. METHODDEF boolean
  472. COM_handler (j_decompress_ptr cinfo)
  473. {
  474.   boolean traceit = (cinfo->err->trace_level >= 1);
  475.   INT32 length;
  476.   unsigned int ch;
  477.   unsigned int lastch = 0;
  478.  
  479.   length = jpeg_getc(cinfo) << 8;
  480.   length += jpeg_getc(cinfo);
  481.   length -= 2;            /* discount the length word itself */
  482.  
  483.   if (traceit)
  484.     fprintf(stderr, "Comment, length %ld:\n", (long) length);
  485.  
  486.   while (--length >= 0) {
  487.     ch = jpeg_getc(cinfo);
  488.     if (traceit) {
  489.       /* Emit the character in a readable form.
  490.        * Nonprintables are converted to \nnn form,
  491.        * while \ is converted to \\.
  492.        * Newlines in CR, CR/LF, or LF form will be printed as one newline.
  493.        */
  494.       if (ch == '\r') {
  495.     fprintf(stderr, "\n");
  496.       } else if (ch == '\n') {
  497.     if (lastch != '\r')
  498.       fprintf(stderr, "\n");
  499.       } else if (ch == '\\') {
  500.     fprintf(stderr, "\\\\");
  501.       } else if (isprint(ch)) {
  502.     putc(ch, stderr);
  503.       } else {
  504.     fprintf(stderr, "\\%03o", ch);
  505.       }
  506.       lastch = ch;
  507.     }
  508.   }
  509.  
  510.   if (traceit)
  511.     fprintf(stderr, "\n");
  512.  
  513.   return TRUE;
  514. }
  515.  
  516.  
  517. /*
  518.  * The main program.
  519.  */
  520.  
  521. GLOBAL int
  522. main (int argc, char **argv)
  523. {
  524.   struct jpeg_decompress_struct cinfo;
  525.   struct jpeg_error_mgr jerr;
  526. #ifdef PROGRESS_REPORT
  527.   struct cdjpeg_progress_mgr progress;
  528. #endif
  529.   int file_index;
  530.   djpeg_dest_ptr dest_mgr = NULL;
  531.   FILE * input_file;
  532.   FILE * output_file;
  533.   JDIMENSION num_scanlines;
  534.  
  535.   /* On Mac, fetch a command line. */
  536. #ifdef USE_CCOMMAND
  537.   argc = ccommand(&argv);
  538. #endif
  539.  
  540.   progname = argv[0];
  541.   if (progname == NULL || progname[0] == 0)
  542.     progname = "djpeg";        /* in case C library doesn't provide it */
  543.  
  544.   /* Initialize the JPEG decompression object with default error handling. */
  545.   cinfo.err = jpeg_std_error(&jerr);
  546.   jpeg_create_decompress(&cinfo);
  547.   /* Add some application-specific error messages (from cderror.h) */
  548.   jerr.addon_message_table = addon_message_table;
  549.   jerr.first_addon_message = JMSG_FIRSTADDONCODE;
  550.   jerr.last_addon_message = JMSG_LASTADDONCODE;
  551.   /* Insert custom COM marker processor. */
  552.   jpeg_set_marker_processor(&cinfo, JPEG_COM, COM_handler);
  553.  
  554.   /* Now safe to enable signal catcher. */
  555. #ifdef NEED_SIGNAL_CATCHER
  556.   sig_cinfo = (j_common_ptr) &cinfo;
  557.   signal(SIGINT, signal_catcher);
  558. #ifdef SIGTERM            /* not all systems have SIGTERM */
  559.   signal(SIGTERM, signal_catcher);
  560. #endif
  561. #endif
  562.  
  563.   /* Scan command line to find file names. */
  564.   /* It is convenient to use just one switch-parsing routine, but the switch
  565.    * values read here are ignored; we will rescan the switches after opening
  566.    * the input file.
  567.    * (Exception: tracing level set here controls verbosity for COM markers
  568.    * found during jpeg_read_header...)
  569.    */
  570.  
  571.   file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
  572.  
  573. #ifdef TWO_FILE_COMMANDLINE
  574.   /* Must have either -outfile switch or explicit output file name */
  575.   if (outfilename == NULL) {
  576.     if (file_index != argc-2) {
  577.       fprintf(stderr, "%s: must name one input and one output file\n",
  578.           progname);
  579.       usage();
  580.     }
  581.     outfilename = argv[file_index+1];
  582.   } else {
  583.     if (file_index != argc-1) {
  584.       fprintf(stderr, "%s: must name one input and one output file\n",
  585.           progname);
  586.       usage();
  587.     }
  588.   }
  589. #else
  590.   /* Unix style: expect zero or one file name */
  591.   if (file_index < argc-1) {
  592.     fprintf(stderr, "%s: only one input file\n", progname);
  593.     usage();
  594.   }
  595. #endif /* TWO_FILE_COMMANDLINE */
  596.  
  597.   /* Open the input file. */
  598.   if (file_index < argc) {
  599.     if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
  600.       fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
  601.       exit(EXIT_FAILURE);
  602.     }
  603.   } else {
  604.     /* default input file is stdin */
  605. #ifdef USE_SETMODE        /* need to hack file mode? */
  606.     setmode(fileno(stdin), O_BINARY);
  607. #endif
  608. #ifdef USE_FDOPEN        /* need to re-open in binary mode? */
  609.     if ((input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
  610.       fprintf(stderr, "%s: can't open stdin\n", progname);
  611.       exit(EXIT_FAILURE);
  612.     }
  613. #else
  614.     input_file = stdin;
  615. #endif
  616.   }
  617.  
  618.   /* Open the output file. */
  619.   if (outfilename != NULL) {
  620.     if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
  621.       fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
  622.       exit(EXIT_FAILURE);
  623.     }
  624.   } else {
  625.     /* default output file is stdout */
  626. #ifdef USE_SETMODE        /* need to hack file mode? */
  627.     setmode(fileno(stdout), O_BINARY);
  628. #endif
  629. #ifdef USE_FDOPEN        /* need to re-open in binary mode? */
  630.     if ((output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
  631.       fprintf(stderr, "%s: can't open stdout\n", progname);
  632.       exit(EXIT_FAILURE);
  633.     }
  634. #else
  635.     output_file = stdout;
  636. #endif
  637.   }
  638.  
  639. #ifdef PROGRESS_REPORT
  640.   /* Enable progress display, unless trace output is on */
  641.   if (jerr.trace_level == 0) {
  642.     progress.pub.progress_monitor = progress_monitor;
  643.     progress.completed_extra_passes = 0;
  644.     progress.total_extra_passes = 0;
  645.     progress.percent_done = -1;
  646.     cinfo.progress = &progress.pub;
  647.   }
  648. #endif
  649.  
  650.   /* Specify data source for decompression */
  651.   jpeg_stdio_src(&cinfo, input_file);
  652.  
  653.   /* Read file header, set default decompression parameters */
  654.   (void) jpeg_read_header(&cinfo, TRUE);
  655.  
  656.   /* Adjust default decompression parameters by re-parsing the options */
  657.   file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
  658.  
  659.   /* Initialize the output module now to let it override any crucial
  660.    * option settings (for instance, GIF wants to force color quantization).
  661.    */
  662.   switch (requested_fmt) {
  663. #ifdef BMP_SUPPORTED
  664.   case FMT_BMP:
  665.     dest_mgr = jinit_write_bmp(&cinfo, FALSE);
  666.     break;
  667.   case FMT_OS2:
  668.     dest_mgr = jinit_write_bmp(&cinfo, TRUE);
  669.     break;
  670. #endif
  671. #ifdef GIF_SUPPORTED
  672.   case FMT_GIF:
  673.     dest_mgr = jinit_write_gif(&cinfo);
  674.     break;
  675. #endif
  676. #ifdef PPM_SUPPORTED
  677.   case FMT_PPM:
  678.     dest_mgr = jinit_write_ppm(&cinfo);
  679.     break;
  680. #endif
  681. #ifdef RLE_SUPPORTED
  682.   case FMT_RLE:
  683.     dest_mgr = jinit_write_rle(&cinfo);
  684.     break;
  685. #endif
  686. #ifdef TARGA_SUPPORTED
  687.   case FMT_TARGA:
  688.     dest_mgr = jinit_write_targa(&cinfo);
  689.     break;
  690. #endif
  691.   default:
  692.     ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);
  693.     break;
  694.   }
  695.   dest_mgr->output_file = output_file;
  696.  
  697.   /* Start decompressor */
  698.   jpeg_start_decompress(&cinfo);
  699.  
  700.   /* Write output file header */
  701.   (*dest_mgr->start_output) (&cinfo, dest_mgr);
  702.  
  703.   /* Process data */
  704.   while (cinfo.output_scanline < cinfo.output_height) {
  705.     num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
  706.                     dest_mgr->buffer_height);
  707.     (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
  708.   }
  709.  
  710. #ifdef PROGRESS_REPORT
  711.   /* Hack: count final pass as done in case finish_output does an extra pass.
  712.    * The library won't have updated completed_passes.
  713.    */
  714.   progress.pub.completed_passes = progress.pub.total_passes;
  715. #endif
  716.  
  717.   /* Finish decompression and release memory.
  718.    * I must do it in this order because output module has allocated memory
  719.    * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
  720.    */
  721.   (*dest_mgr->finish_output) (&cinfo, dest_mgr);
  722.   jpeg_finish_decompress(&cinfo);
  723.   jpeg_destroy_decompress(&cinfo);
  724.  
  725. #ifdef PROGRESS_REPORT
  726.   /* Clear away progress display */
  727.   if (jerr.trace_level == 0) {
  728.     fprintf(stderr, "\r                \r");
  729.     fflush(stderr);
  730.   }
  731. #endif
  732.  
  733.   /* All done. */
  734.   exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
  735.   return 0;            /* suppress no-return-value warnings */
  736. }
  737.